package com.wusuowei.oauthserver.ucenter.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wusuowei.oauthserver.ucenter.mapper.MenuMapper;
import com.wusuowei.oauthserver.ucenter.mapper.RoleMapper;
import com.wusuowei.oauthserver.ucenter.model.dto.UserExt;
import com.wusuowei.oauthserver.ucenter.model.po.Menu;
import com.wusuowei.oauthserver.ucenter.model.po.Role;
import com.wusuowei.oauthserver.ucenter.model.vo.AuthParamsVo;
import com.wusuowei.oauthserver.ucenter.service.AuthService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @description 认证中心入口
 * @author LGY
 * @date 2023/04/11 18:59
 * @version 1.0.0
 */
@Slf4j
@Service
public class UserServiceImpl implements UserDetailsService {

    @Autowired
    MenuMapper menuMapper;

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    ApplicationContext applicationContext;

    /**
     * @description 封装前端传来的参数，根据不同类型调用不同的认证方式进行认证
     * @param s s
     * @return {@link UserDetails }
     * @author LGY
     * @date 2023/03/31 17:22
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        AuthParamsVo paramsVo = null;
        try {
            paramsVo = JSON.parseObject(s, AuthParamsVo.class);
        } catch (Exception e) {
            throw new RuntimeException("认证请求数据格式不对");
        }
        //认证方式,
        String authType = paramsVo.getAuthType();
        //从spring容器中拿具体的认证bean实例
        AuthService authService = applicationContext.getBean(authType + "_authservice", AuthService.class);
        //开始认证,认证成功拿到用户信息
        UserExt UserExt = authService.execute(paramsVo);

        return getUserPrincipal(UserExt);
    }

    public UserDetails getUserPrincipal(UserExt user) {

        String password = user.getPassword();
        //查询用户权限
        List<Menu> menus = menuMapper.selectPermissionByUserId(user.getId());
        List<String> permissions = new ArrayList<>();
        if (menus.size() <= 0) {
            //用户权限,如果不加则报Cannot pass a null GrantedAuthority collection
            permissions.add("p1");
        } else {
            menus.forEach(menu -> {
                permissions.add("ROLE_" + menu.getPerms());
            });
        }
        //将用户权限放在XcUserExt中
        //user.setPermissions(permissions);
        //为了安全在令牌中不放密码
        user.setPassword(null);
        //将user对象转json
        String userString = JSON.toJSONString(user);
        String[] authorities = permissions.toArray(new String[0]);

        //这里会将
        UserDetails userDetails = User.withUsername(userString).password(password).authorities(getUserAuthority(user.getId())).build();
        return userDetails;
    }

    public List<GrantedAuthority> getUserAuthority(Long userId) {
        //  格式ROLE_admin,ROLE_common,system:user:resetPwd,system:role:delete,system:user:list,system:menu:query,system:menu:list,system:menu:add,system:user:delete,system:role:list,system:role:menu,system:user:edit,system:user:query,system:role:edit,system:user:add,system:user:role,system:menu:delete,system:role:add,system:role:query,system:menu:edit
        String authority = this.getUserAuthorityInfo(userId);
        return AuthorityUtils.commaSeparatedStringToAuthorityList(authority);
    }

    public String getUserAuthorityInfo(Long userId) {
        StringBuffer authority=new StringBuffer();
        // 根据用户id获取所有的角色信息
        List<Role> roleList = roleMapper.selectList(new QueryWrapper<Role>().inSql("id", "SELECT role_id FROM sys_user_role WHERE user_id=" + userId));
        if(roleList.size()>0){
            String roleCodeStrs = roleList.stream().map(r -> "ROLE_" + r.getCode()).collect(Collectors.joining(","));
            authority.append(roleCodeStrs);
        }
        // 遍历所有的角色，获取所有菜单权限 而且不重复
        Set<String> menuCodeSet=new HashSet<>();
        for(Role sysRole:roleList){
            List<Menu> sysMenuList = menuMapper.selectList(new QueryWrapper<Menu>().inSql("id", "SELECT menu_id FROM sys_role_menu WHERE role_id=" + sysRole.getId()));
            for(Menu sysMenu:sysMenuList){
                String perms=sysMenu.getPerms();
                if(StringUtils.isNotEmpty(perms)){
                    menuCodeSet.add(perms);
                }
            }
        }
        if(menuCodeSet.size()>0){
            authority.append(",");
            String menuCodeStrs = menuCodeSet.stream().collect(Collectors.joining(","));
            authority.append(menuCodeStrs);
        }
        System.out.println("authority:"+authority.toString());
        return authority.toString();
    }
}
